package com.javasws.springsecuritydemo.config;

import com.javasws.springsecuritydemo.handler.MyAccessDeniedHandler;
import com.javasws.springsecuritydemo.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @author by javasws on 2021/11/28.
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Bean
    public PasswordEncoder getPw() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        // 设置数据源
        jdbcTokenRepository.setDataSource(dataSource);
        // 第一次启动开启，第二次启动注释掉
//        jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 表单提交
        http.formLogin()
                .usernameParameter("username123")
                .passwordParameter("password123")
                // 自定义登录页面
                .loginPage("/showLogin")
                // 必须和表单提交的接口一样，会去执行自定义登录逻辑
                .loginProcessingUrl("/login")
                //登录成功后跳转的页面
                .successForwardUrl("/toMain")
                .failureForwardUrl("/toError");
//                .successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
//                .successHandler(new MyAuthenticationSuccessHandler("/main.html"))
//                .failureHandler(new MyAuthenticationFailureHandler("/error.html"));
        // 授权
        http.authorizeRequests()
                // 设置不需要认证的部分
                .antMatchers("/error.html").permitAll()
//                .antMatchers("/login.html").permitAll()
                .antMatchers("/showLogin").access("permitAll")
                // 放行静态资源
//                .antMatchers("/css/**", "/js/**", "/images/**").permitAll()
                //基于权限
//                .antMatchers("/main1.html").hasAuthority("admin1")
//                .antMatchers("/main1.html").hasRole("ROLE_abc")
                //基于角色
//                .antMatchers("/main1.html").hasRole("abc")
//                .antMatchers("/main1.html").access("hasRole('abc')")
//                .antMatchers("/main1.html").hasAnyRole("abc","abC")
//                .antMatchers("/main1.html").hasIpAddress("127.0.0.1")
                // 放行后缀和正则表达式
//                .antMatchers("/**/*.png").permitAll()
//                .regexMatchers(".+[.]png").permitAll()
//                .regexMatchers("/demo").permitAll()
//                .regexMatchers(HttpMethod.POST, "/demo").permitAll()
//                .mvcMatchers("/demo").servletPath("/test").permitAll()
                // 所有页面必须有人才能访问，必须登录
                .anyRequest().authenticated();
        // 自定义access方法
//                .anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");
        //异常处理
        http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);
        // 记住我
        http.rememberMe()
                // 设置数据源
                .tokenRepository(persistentTokenRepository)
                //设置超时
                .tokenValiditySeconds(60)
                //传入userDetails
                .userDetailsService(userDetailsService);
        //退出
        http.logout()
                // 自定义退出成功后跳转的页面
                .logoutSuccessUrl("/login.html");

        // 关闭csrf
//        http.csrf().disable();

    }
}
